home *** CD-ROM | disk | FTP | other *** search
/ Revista CD Expert 8 / Revista CD Expert nº 08 CD1.iso / Utilitarios / Programacao / MS-DOS Interrupt List / inter60e / INTLIST.E < prev    next >
Text File  |  1998-08-30  |  48KB  |  1,672 lines

  1. /****************************************************************/
  2. /*    EEL code file for editing the Interrupt List        */
  3. /*                                */
  4. /*    Written by Ralf Brown                    */
  5. /*    LastEdit:  30 Aug 98                    */
  6. /*                                */
  7. /*  This EEL file adds the following keybindings:        */
  8. /*    Shf-Alt-A add an Access: section to the current entry    */
  9. /*    Shf-Alt-B add another BUG: to the current entry           */
  10. /*    Shf-Alt-D add a Desc: section to the current entry    */
  11. /*    Sft-Alt-I add an InstallCheck: section to current entry    */
  12. /*    Shf-Alt-R add a Range: section to the current entry       */
  13. /*    Shf-Alt-S add a Size: section to the current entry    */
  14. /*    Alt-I    add an Index: section to the current entry;    */
  15. /*         add another Index: line if already on Index:    */
  16. /*      Alt-N   add a new note to current entry or data struct  */
  17. /*      Alt-P   add a Program: section to the current entry     */
  18. /*      Alt-R   insert Return: at start of line                 */
  19. /*    Alt-S    insert SeeAlso: at start of line; add another    */
  20. /*         SeeAlso: line if already on SeeAlso:        */
  21. /*    F11    insert a blank separator line            */
  22. /*    ^F11    create Format of: header            */
  23. /*    Shf-F11    create Values for: header            */
  24. /*    Alt-F11 create Call with: header            */
  25. /*    Alt-F12 create Bitfield for: header            */
  26. /*    F12    add the interrupt number to the separator line    */
  27. /*        preceding the current entry            */
  28. /*    ^F12    jump to a specified entry            */
  29. /*                                */
  30. /*  It adds the following unbound commands:                */
  31. /*      renumber-tables                            */
  32. /*    make-distribution                    */
  33. /*      filter-region                        */
  34. /*        run region through a specified command; by      */
  35. /*               default, the program is given the region on its */
  36. /*         stdin and its stdout is used to replace the    */
  37. /*        region; if one or two "%s" are given, they    */
  38. /*        will be replaced by the input and output (resp) */
  39. /*        file the program should use.            */
  40. /*                                */ 
  41. /*  Other:                            */
  42. /*    adds intlist-mode for .LST and .1ST files        */
  43. /*    switches current buffer into intlist-mode on loading    */
  44. /*      maintains a table counter which is inserted each time   */
  45. /*        a table is created in the text                */
  46. /*      performs syntax highlighting (Epsilon v7+)        */
  47. /****************************************************************/
  48.  
  49. #include "eel.h"
  50. #if EELVERSION >= 70
  51. #include "colcode.h"
  52. #endif /* Epsilon v7.0+ */
  53.  
  54. keytable intlist_tab ;            /* key table for IntList mode */
  55.  
  56. /* on repeated F12, how often to display number of entries processed */
  57. /* for fast 386, every 100; for a Pentium, at least 300 or the message */
  58. /* line will lag way behind the actual progress */
  59. #define NUMBER_INT_PROGRESS_INTERVAL 500
  60.  
  61. /*=============================================================*/
  62. /*    Global Variables                           */
  63. /*=============================================================*/
  64.  
  65. /* table headings */
  66. char str_format_of[] = "Format of " ;
  67. char str_bitfields_for[] = "Bitfields for " ;
  68.  
  69. /* section names within an entry */
  70. char size_section[] = "Size:\t" ;
  71. char access_section[] = "Access:\t" ;
  72. char return_section[] = "Return: " ;
  73. char program_section[] = "Program: " ;
  74. char desc_section[] = "Desc:\t" ;
  75. char install_section[] = "InstallCheck:" ;
  76. char range_section[] = "Range:\t" ;
  77. char notes_section[] = "Notes*:\t" ;
  78. char bugs_section[] = "BUGS*:\t" ;
  79. char example_section[] = "Example: " ;
  80. char seealso_section[] = "SeeAlso: " ;
  81. char index_section[] = "Index:\t" ;
  82.  
  83. #if EELVERSION >= 70
  84. char all_sections[] = "Return:|SeeAlso:|Program:|Desc:|Range:|Notes*:|BUGS*:|Example:|Index:|Access:|InstallCheck:|Size:" ;
  85. char indented_sections[] = "[\t ]*(Return|Notes*):" ;
  86. char table_headers[] = "INT |Format |Values |Bitfields |MEM |CMOS |MSR |CALL |PORT |Call |OPCODE |I2C " ;
  87. #endif /* Epsilon v7.0+ */
  88.  
  89. /*char table_ID_letters[] = "0123456789CFIMPRS" ;*/
  90. char table_ID_letters[] = "09CFIMPRS" ;
  91. #define ID_LETTER_OFFSET 2
  92.  
  93. char *(section_order[13]) ;
  94. char *(list_files[13]) ;
  95.  
  96. #if EELVERSION >= 90
  97. // Lugaru renamed the variable on us!
  98. #define strip_returns translation_type
  99. #endif /* EELVERSION >= 90 */
  100.  
  101. when_loading()
  102. {
  103.    /* list the sections of an entry in the order they should appear (if */
  104.    /* present at all) */
  105.    section_order[0] = size_section ;
  106.    section_order[1] = access_section ;
  107.    section_order[2] = return_section ;
  108.    section_order[3] = program_section ;
  109.    section_order[4] = desc_section ;
  110.    section_order[5] = install_section ;
  111.    section_order[6] = range_section ;
  112.    section_order[7] = notes_section ;
  113.    section_order[8] = bugs_section ;
  114.    section_order[9] = example_section ;
  115.    section_order[10] = seealso_section ;
  116.    section_order[11] = index_section ;
  117.    section_order[12] = NULL ;
  118.    /* list the files comprising the full interrupt list */
  119.    list_files[0] = "cmos.lst" ;
  120.    list_files[1] = "farcall.lst" ;
  121.    list_files[2] = "memory.lst" ;
  122.    list_files[3] = "ports.lst" ;
  123.    list_files[4] = "interrup.lst" ;
  124.    list_files[5] = "tables.lst" ;
  125.    list_files[6] = "msr.lst" ;
  126.    list_files[7] = "biblio.lst" ;
  127.    list_files[8] = "glossary.lst" ;
  128.    list_files[9] = "opcodes.lst" ;
  129.    list_files[10] = "smm.lst" ;
  130.    list_files[11] = "i2c.lst" ;
  131.    list_files[12] = NULL ;
  132. }
  133.  
  134. /*=============================================================*/
  135. /*    Buffer-specific variables                       */
  136. /*=============================================================*/
  137.  
  138. buffer spot table_counter ;
  139.  
  140. /*=============================================================*/
  141. /*=============================================================*/
  142.  
  143. int empty_line()
  144. {
  145.    return (character(point-1) == '\n' && character(point) == '\n') ;
  146. }
  147.  
  148. /*=============================================================*/
  149. /*=============================================================*/
  150.  
  151. int is_separator_line()
  152. {
  153.    return (empty_line() || parse_string(1,"--------",NULL)) ;
  154. }
  155.  
  156. /*=============================================================*/
  157. /* search in the specified direction (1 = forward, -1 = back)  */
  158. /* for the next entry separator line                   */
  159. /*=============================================================*/
  160.  
  161. int to_separator_line(dir)
  162. int dir ;
  163. {
  164.    nl_reverse() ;
  165.    return search(dir,"\n--------") ;
  166. }
  167.  
  168. /*=============================================================*/
  169. /* move to the location where the specified section of an      */
  170. /* entry begins (if present) or should begin (if not)           */
  171. /*=============================================================*/
  172.  
  173. int to_section_start(section)
  174. char *section ;
  175. {
  176.    int i, j, len ;
  177.  
  178.    for (i = 0 ; section_order[i] ; i++)
  179.       if (strcmp(section,section_order[i]) == 0)
  180.      break ;
  181.    if (section_order[i])
  182.       {
  183.       while (!is_separator_line())
  184.      {
  185.      for (j = i ; section_order[j] ; j++)
  186.         if (parse_string(1,section_order[j],NULL))
  187.            {
  188.            if ((len = parse_string(1,section,NULL)) != 0)
  189.           {
  190.           point += len ;
  191.           return 1 ;    /* section already exists */
  192.           }
  193.            return 0 ;    /* section nonexistent, but found position */
  194.            }
  195.      if (!nl_forward())
  196.         break ;
  197.      }
  198.       return 0 ;    /* section does not yet exist */
  199.       }
  200.    else
  201.       return 0 ;    /* section not found */
  202. }
  203.  
  204. /*=============================================================*/
  205. /*=============================================================*/
  206.  
  207. int make_section(section,start_entry,name)
  208. char *section, *name ;
  209. int start_entry ;
  210. {
  211.    int start = point ;
  212.  
  213.    if (start_entry)
  214.       {
  215.       if (!to_separator_line(-1))  /* find previous separator line */
  216.      {
  217.      point = start ;
  218.      say("Not in an interrupt entry") ;
  219.      return 0 ;
  220.      }
  221.       }
  222.    else
  223.       {
  224.       to_begin_line() ;
  225.       while (!empty_line() && !parse_string(1,"\n--------",NULL))
  226.      if (!nl_reverse())
  227.         break ;
  228.       }
  229.    point++ ;                 /* skip the newline */
  230.    nl_forward() ;             /* advance to first line of entry */
  231.    if (!to_section_start(section))
  232.       {
  233.       if (name)
  234.      stuff(name) ;
  235.       else
  236.      stuff(section) ;
  237.       stuff("\n") ;
  238.       point-- ;              /* back up over inserted newline */
  239.       return 1 ;
  240.       }
  241.    else
  242.       return 0 ;
  243.    return 2 ;  /* just in case */
  244. }
  245.  
  246. /*=============================================================*/
  247. /*=============================================================*/
  248.  
  249. int pluralize_section(plural)
  250. char plural ;
  251. {
  252.    point -= 3 ;
  253.    if (curchar() != plural)        /* already plural ? */
  254.       {
  255.       point++ ;
  256.       insert(plural) ;
  257.       }
  258.    nl_forward() ;
  259.    while (!is_separator_line() && parse_string(1,"[ \t]",NULL))
  260.       nl_forward() ;
  261.    stuff("\t\n") ;
  262.    point-- ;
  263. }
  264.  
  265. /*=============================================================*/
  266. /* Add "SeeAlso: " to the beginning of the current line unless */
  267. /* it is already present; in that case, insert a fresh line    */
  268. /* containing just a SeeAlso: and position the cursor at the   */
  269. /* end of the new line                           */
  270. /*=============================================================*/
  271.  
  272. command see_also() on intlist_tab[ALT('s')]
  273. {
  274.    to_begin_line() ;
  275.    if (parse_string(1,"SeeAlso: ",NULL) == 0)
  276.       stuff("SeeAlso: ") ;
  277.    else
  278.       {
  279.       nl_forward() ;
  280.       stuff("SeeAlso: \n") ;
  281.       point-- ;
  282.       }
  283. }
  284.  
  285. /*=============================================================*/
  286. /* Add a Desc: section if the current entry does not already   */
  287. /* have one; if there is already a Desc: section, move to the  */
  288. /* start of it                               */
  289. /*=============================================================*/
  290.  
  291. command access() on intlist_tab[ALT('A')]
  292. {
  293.    make_section(access_section,1,NULL) ;
  294. }
  295.  
  296. /*=============================================================*/
  297. /* Add a Desc: section if the current entry does not already   */
  298. /* have one; if there is already a Desc: section, move to the  */
  299. /* start of it                               */
  300. /*=============================================================*/
  301.  
  302. command desc() on intlist_tab[ALT('D')]
  303. {
  304.    make_section(desc_section,1,NULL) ;
  305. }
  306.  
  307. /*=============================================================*/
  308. /* Add a InstallCheck: section if the current entry does not   */
  309. /* already have one; if there is already a InstallCheck:       */
  310. /* section, move to the start of it                   */
  311. /*=============================================================*/
  312.  
  313. command instcheck() on intlist_tab[ALT('I')]
  314. {
  315.    make_section(install_section,1,NULL) ;
  316. }
  317.  
  318. /*=============================================================*/
  319. /* Add a Range: section if the current entry does not already  */
  320. /* have one; if there is already a Range: section, move to the */
  321. /* start of it                               */
  322. /*=============================================================*/
  323.  
  324. command range() on intlist_tab[ALT('R')]
  325. {
  326.    make_section(range_section,1,NULL) ;
  327. }
  328.  
  329. /*=============================================================*/
  330. /* Add a Size: section if the current entry does not already   */
  331. /* have one; if there is already a Size: section, move to the  */
  332. /* start of it                               */
  333. /*=============================================================*/
  334.  
  335. command memsize() on intlist_tab[ALT('S')]
  336. {
  337.    make_section(size_section,1,NULL) ;
  338. }
  339.  
  340. /*=============================================================*/
  341. /* Add a "Program: " section to the current entry if it does   */
  342. /* not have one; otherwise, move to the beginning of the       */
  343. /* Program: section                           */
  344. /*=============================================================*/
  345.  
  346. command program() on intlist_tab[ALT('p')]
  347. {
  348.    make_section(program_section,1,NULL) ;
  349. }
  350.  
  351. /*=============================================================*/
  352. /* Add an "Index: " section to the current entry if it does    */
  353. /* not have one; otherwise, move to the beginning of the       */
  354. /* Index: section                           */
  355. /*=============================================================*/
  356.  
  357. command add_index() on intlist_tab[ALT('i')]
  358. {
  359.    to_begin_line() ;
  360.    if (parse_string(1,"Index:",NULL))
  361.       {
  362.       while (parse_string(1,"Index:",NULL))
  363.      nl_forward() ;
  364.       stuff("Index:\t\n") ;
  365.       point-- ;
  366.       }
  367.    else
  368.       make_section(index_section,1,NULL) ;
  369. }
  370.  
  371. /*=============================================================*/
  372. /*=============================================================*/
  373.  
  374. command bug() on intlist_tab[ALT('B')]
  375. {
  376.    if (!make_section(bugs_section,1,"BUG:\t"))
  377.       pluralize_section('S') ;
  378. }
  379.  
  380. /*=============================================================*/
  381. /* Add "Note: " section to the current entry; change an        */
  382. /* existing Note: to Notes: and position at end of Note:       */
  383. /* section.                               */
  384. /*=============================================================*/
  385.  
  386. command add_note() on intlist_tab[ALT('n')]
  387. {
  388.    if (!make_section(notes_section,0,"Note:\t"))
  389.       pluralize_section('s') ;
  390. }
  391.  
  392. /*=============================================================*/
  393. /* Insert "Return: " at the beginning of the current line, if  */
  394. /* not already present                           */
  395. /*=============================================================*/
  396.  
  397. command returns() on intlist_tab[ALT('r')]
  398. {
  399.    int start = point ;
  400.    
  401.    to_begin_line() ;
  402.    if (parse_string(1,return_section,NULL) == 0)
  403.       stuff(return_section) ;
  404.    else
  405.       point = start ;
  406. }
  407.  
  408. /*=============================================================*/
  409. /* insert a line of dashes prior to the current cursor line    */
  410. /*=============================================================*/
  411.  
  412. command separator_line() on intlist_tab[FKEY(11)]
  413. {
  414.    int i ;
  415.  
  416.    to_begin_line() ;
  417.    for (i = 0 ; i < 45 ; i++)
  418.       insert('-') ;
  419.    insert('\n') ;
  420. }
  421.  
  422. /*=============================================================*/
  423. /*=============================================================*/
  424.  
  425. void insert_table_counter()
  426. {
  427.    char counter[6] ;
  428.    save_var point = *table_counter + 4 ;
  429.  
  430.    /* increment that table counter */
  431.    while (curchar() >= '0')
  432.       {
  433.       if (curchar() < '9')
  434.      {
  435.      replace(point,curchar()+1) ;
  436.      break ;
  437.      }
  438.       else
  439.      {
  440.      replace(point,'0') ;
  441.      point-- ;
  442.      }
  443.       }
  444.    restore_vars() ;
  445.    /* and now insert the incremented value at point */
  446.    stuff("(Table ") ;
  447.    grab(*table_counter,*table_counter+5,counter) ;
  448.    stuff(counter) ;
  449.    stuff(")") ;
  450. }
  451.  
  452. /*=============================================================*/
  453. /* type the name of a structure, then invoke this function     */
  454. /* to create the "Format of X:" and "Offset Size Descr" lines  */
  455. /*=============================================================*/
  456.  
  457. command structure_header() on intlist_tab[FCTRL(11)]
  458. {
  459.    int start = point ;
  460.  
  461.    to_begin_line() ;
  462.    if (parse_string(1,str_format_of,NULL) == 0)
  463.       {
  464.       stuff(str_format_of) ;
  465.       to_end_line() ;
  466.       stuff(":\nOffset\tSize\tDescription\t") ;
  467.       insert_table_counter() ;
  468.       stuff("\n 00h\t") ;
  469.       }
  470.    else
  471.       point = start ;
  472. }
  473.  
  474. /*=============================================================*/
  475. /* Turn the current line into the header for a "Values of"     */
  476. /* section                               */
  477. /*=============================================================*/
  478.  
  479. command value_header() on intlist_tab[FSHIFT(11)]
  480. {
  481.    int start = point ;
  482.    
  483.    to_begin_line() ;
  484.    if (parse_string(1,"Values for ",NULL) == 0)
  485.       {
  486.       insert_table_counter() ;
  487.       stuff("\nValues for ") ;
  488.       to_end_line() ;
  489.       stuff(":\n ") ;
  490.       }
  491.    else
  492.       point = start ;
  493. }
  494.  
  495. /*=============================================================*/
  496. /* Turn the current line into the header of a "Call with"      */
  497. /* section                               */
  498. /*=============================================================*/
  499.  
  500. command call_with_header() on intlist_tab[FALT(11)]
  501. {
  502.    int start = point ;
  503.    
  504.    to_begin_line() ;
  505.    if (parse_string(1,"Call ",NULL) == 0)
  506.       {
  507.       insert_table_counter() ;
  508.       stuff("\nCall ") ;
  509.       to_end_line() ;
  510.       if (character(point-1) != ' ')
  511.      stuff(" ") ;
  512.       stuff("with:\n") ;
  513.       }
  514.    else
  515.       point = start ;
  516. }
  517.  
  518. /*=============================================================*/
  519. /* Turn the current line into the header of a "Bitfield for"   */
  520. /* section                               */
  521. /*=============================================================*/
  522.  
  523. command bitfields_for_header() on intlist_tab[FALT(12)]
  524. {
  525.    int start = point ;
  526.    
  527.    to_begin_line() ;
  528.    if (parse_string(1,str_bitfields_for,NULL) == 0)
  529.       {
  530.       stuff(str_bitfields_for) ;
  531.       to_end_line() ;
  532.       stuff(":\nBit(s)\tDescription\t") ;
  533.       insert_table_counter() ;
  534.       stuff("\n ") ;
  535.       }
  536.    else
  537.       point = start ;
  538. }
  539.  
  540. /*=============================================================*/
  541. /*=============================================================*/
  542.  
  543. char grab_int_entry_number(func_num)
  544. char *func_num ;
  545. {
  546.    int i ;
  547.    char c ;
  548.    
  549.    point += 4 ;                /* skip the "INT " */
  550.    func_num[0] = curchar() ;        /* grab the interrupt number */
  551.    point++ ;
  552.    func_num[1] = curchar() ;
  553.    nl_forward() ;            /* skip to second line of entry */
  554.    if (parse_string(1,"[ \t]*A[LHX][ \t]=[ \t][0-9A-F][0-9A-F]+h",NULL))
  555.       {
  556.       re_search(1,"[ \t]*A") ;
  557.       c = curchar() ;
  558.       point += 4 ;            /* skip ch and " = " */
  559.       if (c != 'L')
  560.      {
  561.      grab(point,point+((c=='X')?4:2),func_num+2) ;
  562.      point += ((c=='X')?4:2) ;
  563.      func_num[(c=='H')?4:6] = '-' ;    /* grab() stuck a NUL into the string */
  564.      }
  565.       else /* c == 'L' */
  566.      {
  567.      func_num[4] = curchar() ;
  568.      point++ ;
  569.      func_num[5] = curchar() ;
  570.      point ++ ;
  571.      }
  572.       point++ ;
  573.       if (parse_string(1,"[ \t]*subfn [0-9A-F][0-9A-F]+h",NULL))
  574.      {
  575.      re_search(1,"[ \t]*subfn ") ;
  576.      func_num[6] = 'S' ;
  577.      func_num[7] = 'F' ;
  578.      for (i = 0 ; i < 4 ; i++)
  579.         {
  580.         c = curchar() ;
  581.         if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F'))
  582.            {
  583.            func_num[8+i] = c ;
  584.            point++ ;
  585.            }
  586.         else
  587.            break ;
  588.         }
  589.      }
  590.       nl_forward() ;            /* skip to third line of entry */
  591.       }
  592.    if (parse_string(1,"[ \t]*([BCDES][HILPSX]|VxD) = [0-9A-F][0-9A-F]+h",NULL))
  593.       {
  594.       re_search(1,"[ \t]*") ;
  595.       func_num[6] = curchar() ;
  596.       point++ ;
  597.       func_num[7] = c = curchar() ;
  598.       point += 4 ;            /* skip curchar and " = " */
  599.       if (func_num[6] == 'V')        /* VxD has three letters not two... */
  600.      point++ ;
  601.       if (c == 'H' || c == 'L')
  602.      {
  603.      grab(point,point+2,func_num+8) ;
  604.      func_num[10] = '-' ;        /* grab() stuck a NUL into the string */
  605.      }
  606.       else /* c == 'X' || c == 'I' || c == 'P' || c == 'S' */
  607.      {
  608.      grab(point,point+4,func_num+8) ;
  609.      func_num[12] = '-' ;
  610.      }
  611.       }
  612.    return 1 ;                /* successful and have func number */
  613. }
  614.  
  615. /*=============================================================*/
  616.  
  617. char grab_cmos_entry_number(func_num)
  618. char *func_num ;
  619. {
  620.    point += 5 ;                    /* skip the "CMOS " */
  621.    func_num[0] = 'R' ;            /* mark this as a CMOS RAM entry */
  622.    grab(point,point+4,func_num+1) ;
  623.    if (func_num[3] == 'h' && func_num[4] == '-')
  624.       grab(point+4,point+6,func_num+3) ;
  625.    else
  626.       {
  627.       func_num[3] = '-' ;
  628.       func_num[4] = '-' ;
  629.       }
  630.    func_num[5] = '-' ;            /* grab() stuck a NUL into string */
  631.    return 1 ;
  632. }
  633.  
  634. /*=============================================================*/
  635.  
  636. char grab_farcall_entry_number(func_num)
  637. char *func_num ;
  638. {
  639.    point += 5 ;                /* skip the "CALL " */
  640.    func_num[0] = '@' ;            /* mark this as a far call entry */
  641.    grab(point,point+4,func_num+1) ;    /* get segment of address */
  642.    grab(point+6,point+10,func_num+5) ;    /* get offset of address */
  643.    func_num[9] = '-' ;            /* grab() stuck a NUL into string */
  644.    return 1 ;
  645. }
  646.  
  647. /*=============================================================*/
  648.  
  649. char grab_msr_entry_number(func_num)
  650. char *func_num ;
  651. {
  652.    point += 4 ;                /* skip the "MSR " */
  653.    func_num[0] = 'S' ;            /* mark this as an MSR entry */
  654.    grab(point,point+8,func_num+1) ;     /* get the MSR number */
  655.    func_num[9] = '-' ;                  /* grab() stuck a NUL into string */
  656.    return 1 ;
  657. }
  658.  
  659. /*=============================================================*/
  660.  
  661. char grab_memory_entry_number(func_num)
  662. char *func_num ;
  663. {
  664.    point += 4 ;                /* skip the "MEM " */
  665.    func_num[0] = 'M' ;                /* mark this as a memory loc entry */
  666.    grab(point,point+6,func_num+1) ;    /* get segment or high word of addr */
  667.    if (func_num[5] == 'h' && func_num[6] == ':') /* segmented address? */
  668.       grab(point+6,point+10,func_num+5) ;    /* get offset of address */
  669.    else
  670.       {
  671.       grab(point+6,point+8,func_num+7) ;/* get low word of the address */
  672.       func_num[0] = 'm' ;        /* indicate linear address */
  673.       }
  674.    func_num[9] = '-' ;            /* grab() stuck a NUL into string */
  675.    return 1 ;
  676. }
  677.  
  678. /*=============================================================*/
  679.  
  680. char grab_opcode_name(func_num)
  681. char *func_num ;
  682. {
  683.    int i ;
  684.    point += 7 ;                /* skip the "OPCODE " */
  685.    func_num[0] = 'O' ;            /* mark this as an opcode entry */
  686.    for (i = 2 ; i < 12 ; i++)        /* grab the opcode name and stuff */
  687.       {                       /*   it into the header line */
  688.       char c = curchar() ;
  689.       if (c == ' ' || c == '\t')
  690.      break ;
  691.       else
  692.      {
  693.      func_num[i] = c ;
  694.      point++ ;
  695.      }
  696.       }
  697.    return 1 ;
  698. }
  699.  
  700. /*=============================================================*/
  701.  
  702. char grab_port_entry_number(func_num)
  703. char *func_num ;
  704. {
  705.    point += 5 ;                /* skip the "PORT " */
  706.    func_num[0] = 'P' ;            /* mark this as an I/O port entry */
  707.    grab(point,point+4,func_num+1) ;    /* get starting port number */
  708.    func_num[5] = '-' ;            /* grab() stuck a NUL into string */
  709.    if (character(point+4) == '-')
  710.       {
  711.       grab(point+5,point+9,func_num+5) ; /* get ending port number */
  712.       func_num[9] = '-' ;        /* grab() stuck a NUL into string */
  713.       }
  714.    return 1 ;
  715. }
  716.  
  717. /*=============================================================*/
  718.  
  719. char grab_i2c_entry_number(func_num)
  720. char *func_num ;
  721. {
  722.    point += 4 ;                /* skip the "I2C " */
  723.    func_num[0] = 'I' ;            /* mark this as an I2C port entry */
  724.    grab(point,point+2,func_num+1) ;    /* get slave address */
  725.    func_num[3] = '-' ;            /* grab() stuck a NUL into string */
  726.    if (character(point+3) == '/')
  727.       {
  728.       grab(point+4,point+6,func_num+3) ; /* get register address */
  729.       func_num[5] = '-' ;        /* grab() stuck a NUL into string */
  730.       if (character(point+6) != 'h' && character(point+6) != '/')
  731.      {
  732.      grab(point+6,point+8,func_num+5) ; /* get second byte of reg. addr */
  733.      func_num[7] = '-' ;        /* grab() stuck a NUL into string */
  734.      point += 2 ;
  735.      }
  736.       if (character(point+7) == '/')
  737.      {
  738.      func_num[7] = 'S' ;
  739.      func_num[8] = 'F' ;
  740.      grab(point+8,point+10,func_num+9) ;
  741.      func_num[11] = '-' ;
  742.      if (character(point+10) != 'h')
  743.         grab(point+10,point+12,func_num+11) ;
  744.      }
  745.       }
  746.    return 1 ;
  747. }
  748.  
  749. /*=============================================================*/
  750.  
  751. char grab_entry_number(func_num)
  752. char *func_num ;
  753. {
  754.    strcpy(func_num,"-------------") ;    /* 13 dashes */
  755.    point++ ;                /* go to first char of separator line */
  756.    nl_forward() ;            /* go to first line of entry */
  757.    if (parse_string(1,"INT ",NULL))    /* is it an interrupt entry? */
  758.       return grab_int_entry_number(func_num) ;
  759.    else if (parse_string(1,"CMOS ",NULL) != 0)
  760.       return grab_cmos_entry_number(func_num) ;
  761.    else if (parse_string(1,"CALL ",NULL) != 0)
  762.       return grab_farcall_entry_number(func_num) ;
  763.    else if (parse_string(1,"MEM ",NULL) != 0)
  764.       return grab_memory_entry_number(func_num) ;
  765.    else if (parse_string(1,"PORT ",NULL) != 0)
  766.       return grab_port_entry_number(func_num) ;
  767.    else if (parse_string(1,"MSR ",NULL) != 0)
  768.       return grab_msr_entry_number(func_num) ;
  769.    else if (parse_string(1,"OPCODE ",NULL) != 0)
  770.       return grab_opcode_name(func_num) ;
  771.    else if (parse_string(1,"I2C ",NULL) != 0)
  772.       return grab_i2c_entry_number(func_num) ;
  773.    else
  774.       return 0 ;
  775. }
  776.  
  777. /*=============================================================*/
  778. /* Put the interrupt and function number into the separator    */
  779. /* line just above the intlist entry preceding the cursor pos  */
  780. /*=============================================================*/
  781.  
  782. int number_one_int()
  783. {
  784.    char func_num[14] ;            /* 2->int, 4->AX, 6->extra reg, NUL */
  785.    int oldpoint ;
  786.    
  787.    while (to_separator_line(-1))    /* find previous separator line */
  788.       {
  789.       oldpoint = point ;
  790.       if (grab_entry_number(func_num))    /* does it belong to an intlist entry? */
  791.      {                /*   if yes, success, else try again */
  792.      point = oldpoint + 11 ;    /* skip NL and first ten dashes */
  793.      delete(point,point+13) ;    /* replace 13 dashes by the function */
  794.      stuff(func_num) ;        /*   number and extra register */
  795.      point = oldpoint + 9 ;        /* back to category letter position */
  796.      return 1 ;
  797.      }
  798.       point = oldpoint ;
  799.       }
  800.    return 0 ;                /* if we get here, we failed */
  801. }
  802.  
  803. /*=============================================================*/
  804. /* Put the interrupt and function number into the separator    */
  805. /* line just above one or more intlist entries preceding the   */
  806. /* current cursor position, letting user know of progress      */
  807. /*=============================================================*/
  808.  
  809. command number_int() on intlist_tab[FKEY(12)]
  810. {
  811.    int i, hit_top = 0 ;
  812.    
  813.    for (i = 0 ; i < iter ; i++)
  814.       {
  815.       if (!number_one_int())
  816.      {
  817.      hit_top = 1 ;
  818.      say("No prior entry.") ;
  819.      break ;
  820.      }
  821.       if (((i+1) % NUMBER_INT_PROGRESS_INTERVAL) == 0)
  822.      say("%4d...",i+1) ;
  823.       }
  824.    if (iter > 1 && !hit_top)
  825.       say("Done.") ;
  826.    iter = 1 ;
  827. }
  828.  
  829. /*=============================================================*/
  830. /*=============================================================*/
  831.  
  832. int line_has_see_also()
  833. {
  834.    int len ;
  835.    
  836.    to_begin_line() ;
  837.    if ((len = parse_string(1,".*%([sS]ee ",NULL)) != 0)
  838.       {
  839.       point += len ;        /* go to start of cross-reference */
  840.       point += parse_string(1,"also ",NULL) ;
  841.       if (parse_string(1,"INT [0-9A-F]",NULL) ||
  842.       parse_string(1,"A[XHL] =",NULL)
  843.      )
  844.      {
  845.      point++ ;        /* move into reference */
  846.      return 1 ;
  847.      }
  848.       }
  849.    return 0 ;
  850. }
  851.  
  852. /*=============================================================*/
  853. /*=============================================================*/
  854.  
  855. int grab_int_reference(ref)
  856. char *ref ;
  857. {
  858.    int begin, start = point ;
  859.    
  860.    re_search(-1,"[, \t\n]") ;    /* backup to start of reference */
  861.    if (curchar() == '\n')    /* start of line? */
  862.       re_search(1,":[ \t]") ;    /* skip the SeeAlso: */
  863.    else if (character(point-1) == 'T' && character(point-2) == 'N')
  864.       point -= 3 ;
  865.    else
  866.       point++ ;            /* back to start of reference */
  867.    begin = point ;
  868.    re_search(1,"[,\n\"]") ;    /* find end of INT-spec */
  869.    point-- ;
  870.    if (curchar() == '\"')    /* extra string at end of INT-spec? */
  871.       {
  872.       point++ ;
  873.       re_search(1,"[\"\n]") ;    /* if yes, run to end of line or string */
  874.       }
  875.    grab(begin,point,ref) ;
  876.    point = start ;
  877.    return 0 ;
  878. }
  879.  
  880. /*=============================================================*/
  881. /*=============================================================*/
  882.  
  883. int parse_int_name(entry_name,id,extra_string)
  884. char *entry_name, *id, *extra_string ;
  885. {
  886.    int start = point ;
  887.    int i ;
  888.    char c, *last ;
  889.  
  890.    for (i = strlen(entry_name)-1 ; i >= 0 ; i--)
  891.       entry_name[i] = toupper(entry_name[i]) ;
  892.    strcpy(id,"------------") ;
  893.    if (strncmp(entry_name,"INT ",4) == 0)
  894.       {
  895.       id[0] = entry_name[4] ;
  896.       id[1] = entry_name[5] ;
  897.       entry_name += 6 ;
  898.       if (entry_name[0] == '/')
  899.      entry_name++ ;
  900.       }
  901.    else if (to_separator_line(-1))
  902.       {
  903.       id[0] = character(point+11) ;
  904.       id[1] = character(point+12) ;
  905.       }
  906.    point = start ;
  907.    c = entry_name[1] ;
  908.    if (entry_name[0] == 'A' && (c == 'X' || c == 'H' || c == 'L'))
  909.       {
  910.       entry_name += 2 ;
  911.       while (entry_name[0] == ' ' || entry_name[0] == '\t')
  912.      entry_name++ ;
  913.       if (entry_name[0] == '=')
  914.      entry_name++ ;
  915.       while (entry_name[0] == ' ' || entry_name[0] == '\t')
  916.      entry_name++ ;
  917.       if (c != 'L')
  918.      {
  919.          id[2] = entry_name[0] ;
  920.          id[3] = entry_name[1] ;
  921.      }
  922.       if (c == 'X')
  923.      {
  924.      id[4] = entry_name[2] ;
  925.      id[5] = entry_name[3] ;
  926.      entry_name += 4 ;
  927.      }
  928.       else
  929.      {
  930.      if (c == 'L')
  931.         {
  932.         id[2] = entry_name[0] ;
  933.         id[3] = entry_name[1] ;
  934.         }
  935.      entry_name += 2 ;
  936.      }
  937.       if (entry_name[0] == 'H')
  938.      entry_name++ ;
  939.       if (entry_name[0] == '/')
  940.      entry_name++ ;
  941.       }
  942.    if (index("ABCDES",entry_name[0]) && index("HILPSXF",entry_name[1]))
  943.       {
  944.       id[6] = entry_name[0] ;
  945.       c = id[7] = entry_name[1] ;
  946.       entry_name += 2 ;
  947.       while (entry_name[0] == ' ' || entry_name[0] == '\t')
  948.      entry_name++ ;
  949.       if (entry_name[0] == '=')
  950.      entry_name++ ;
  951.       while (entry_name[0] == ' ' || entry_name[0] == '\t')
  952.      entry_name++ ;
  953.       id[8] = entry_name[0] ;
  954.       id[9] = entry_name[1] ;
  955.       if (c != 'H' && c != 'L' && (c != 'F' || entry_name[2] != 'h'))
  956.      {
  957.      id[10] = entry_name[2] ;
  958.      id[11] = entry_name[3] ;
  959.      entry_name += 4 ;
  960.      }
  961.       else
  962.      entry_name += 2 ;
  963.       if (entry_name[0] == 'H')
  964.      entry_name++ ;
  965.       if (entry_name[0] == '/')
  966.      entry_name++ ;
  967.       }
  968.    if (entry_name[0] == '\"')
  969.       {
  970.       entry_name++ ;
  971.       strcpy(extra_string,entry_name) ;
  972.       last = index(extra_string,'\"') ;
  973.       if (last)
  974.      *last = '\0' ;
  975.       }
  976.    else
  977.       extra_string[0] = '\0' ;
  978.    return 0 ;
  979. }
  980.  
  981. /*=============================================================*/
  982. /*=============================================================*/
  983.  
  984. int hex2_to_int(c1,c2)
  985. char c1, c2 ;
  986. {
  987.    if (c1 >= '0' && c1 <= '9')
  988.       c1 -= '0' ;
  989.    else if (c1 >= 'A' && c1 <= 'F')
  990.       c1 = c1 - 'A' + 10 ;
  991.    else if (c1 >= 'a' && c1 <= 'f')
  992.       c1 = c1 - 'a' + 10 ;
  993.    else
  994.       return -1 ;
  995.    if (c2 >= '0' && c2 <= '9')
  996.       c2 -= '0' ;
  997.    else if (c2 >= 'A' && c2 <= 'F')
  998.       c2 = c2 - 'A' + 10 ;
  999.    else if (c2 >= 'a' && c2 <= 'f')
  1000.       c2 = c2 - 'a' + 10 ;
  1001.    else
  1002.       return -1 ;
  1003.    return 16*c1 + c2 ;
  1004. }
  1005.  
  1006. /*=============================================================*/
  1007. /*=============================================================*/
  1008.  
  1009. char hex_digit(val)
  1010. int val ;
  1011. {
  1012.    if (val < 0)
  1013.       return '-' ;
  1014.    else
  1015.       return (val > 9) ? ('A' + val - 10) : ('0' + val) ;
  1016. }
  1017.  
  1018. /*=============================================================*/
  1019. /*=============================================================*/
  1020.  
  1021. int scan_for_entry(entry,extra_str,first_entry)
  1022. char *entry, *extra_str ;
  1023. int *first_entry ;
  1024. {
  1025.    int bestcount = 0 ;
  1026.    int bestmatch = -1 ;
  1027.  
  1028.    if (extra_str) extra_str = 0 ;  /* for now, to avoid compiler warning */
  1029.    *first_entry = 0 ;
  1030.    /* scan for the first entry for the desired interrupt number */
  1031.    while (to_separator_line(1))
  1032.       {
  1033.       point += 2 ;
  1034.       if (character(point) == entry[0] && character(point+1) == entry[1])
  1035.      break ;
  1036.       nl_forward() ;
  1037.       }
  1038.    /* now scan through the entries for the given interrupt number */
  1039.    while (to_separator_line(1))
  1040.       {
  1041.       int i ;
  1042.       char buf[14] ;
  1043.       point += 2 ;
  1044.       grab(point,point+12,buf) ;
  1045.       if ((buf[0] != entry[0] || buf[1] != entry[1]) &&
  1046.       (buf[0] != '-' && buf[1] != '-'))
  1047.      break ;            /* ran out of entries... */
  1048.       for (i = 2 ; i <= 12 ; i++)
  1049.      {
  1050.      if (buf[i] != entry[i])
  1051.         break ;
  1052.      }
  1053.       if (i > bestcount)
  1054.      {
  1055.      bestcount = i ;
  1056.      bestmatch = point ;
  1057.      if (i > 12)
  1058.         break ;            /* found an exact match */
  1059.      }
  1060.       nl_forward() ;
  1061.       }
  1062.    if (bestmatch == -1)
  1063.       return 0 ;            /* we failed */
  1064.    else
  1065.       {
  1066.       *first_entry = bestmatch ;
  1067.       point = bestmatch ;        /* back to best-matching entry */
  1068.       nl_forward() ;
  1069.       return 1 ;            /* we were successful */
  1070.       }
  1071. }
  1072.  
  1073. /*=============================================================*/
  1074. /*=============================================================*/
  1075.  
  1076. int goto_entry(entry_name)
  1077. char *entry_name ;
  1078. {
  1079.    char int_id[13], extra_string[60] ;
  1080.    int start = point, first_entry ;
  1081.    int int_num, curr_int ;
  1082.    char search_str[22] ;
  1083.    
  1084.    parse_int_name(entry_name,int_id,extra_string) ;
  1085.    int_num = hex2_to_int(int_id[0],int_id[1]) ;
  1086.    if (to_separator_line(-1))
  1087.       {
  1088.       if (character(point+11) == '-')
  1089.      curr_int = -1 ;
  1090.       else
  1091.      curr_int = hex2_to_int(character(point+11),character(point+12)) ;
  1092.       if (int_num <= 0)
  1093.      point = 0 ;        /* go to top of file */
  1094.       else
  1095.      {
  1096.      if (curr_int <= 0)
  1097.         point = 0 ;        /* go to top of file */
  1098.      strcpy(search_str,"--------.-") ;
  1099.      search_str[10] = hex_digit((int_num-1) / 16) ;
  1100.      search_str[11] = hex_digit((int_num-1) % 16) ;
  1101.      search_str[12] = '\0' ;
  1102.      if (!re_search( (int_num<=curr_int)?-1:1, search_str))
  1103.         {
  1104.         say("%s not found.",entry_name) ;
  1105.         iter = 1 ;
  1106.         return 0 ;
  1107.         }
  1108.      to_begin_line() ;
  1109.      }
  1110.       }
  1111.    else
  1112.       point = 0 ;
  1113.    if (!scan_for_entry(int_id,extra_string,&first_entry))
  1114.       {
  1115.       say("%s not found.",entry_name) ;
  1116.       if (first_entry)
  1117.      {
  1118.      mark = start ;
  1119.      point = first_entry ;
  1120.      }
  1121.       else
  1122.      point = start ;
  1123.       }
  1124.    if (has_arg)
  1125.      iter = 1 ;                /* don't search repeatedly */
  1126.    return 0 ;
  1127. }
  1128.  
  1129. /*=============================================================*/
  1130. /*=============================================================*/
  1131.  
  1132. command goto_int() on intlist_tab[FCTRL(12)]
  1133. {
  1134.    char entry_name[60], def_entry[60] ;
  1135.    int start = point ;
  1136.  
  1137.    to_begin_line() ;
  1138.    if (parse_string(1,"SeeAlso: ",NULL) != 0)
  1139.       {
  1140.       point += 9 ;        /* skip the SeeAlso: */
  1141.       if (point < start)    /* if we were originally to the right of     */
  1142.      point = start ;    /* current position, go back to original pos */
  1143.       grab_int_reference(def_entry) ;
  1144.       get_strdef(entry_name,"Goto Interrupt",def_entry) ;
  1145.       }
  1146.    else if (line_has_see_also())
  1147.       {
  1148.       grab_int_reference(def_entry) ;
  1149.       get_strdef(entry_name,"Goto Interrupt",def_entry) ;
  1150.       }
  1151.    else
  1152.       get_string(entry_name,"Goto Interrupt: ") ;
  1153.    point = start ;
  1154.    goto_entry(entry_name) ;
  1155.    if (has_arg)
  1156.       iter = 1 ;
  1157. }
  1158.  
  1159. /*=============================================================*/
  1160. /*=============================================================*/
  1161.  
  1162. void maybe_append_table_number()
  1163. {
  1164.    if (parse_string(1,".*\t%(Table ",0) == 0)
  1165.       {
  1166.       int matchsize ;
  1167.       /* if the pattern didn't match, there is no table number, */
  1168.       /* so add it */
  1169.       to_end_line() ;
  1170.       matchsize = parse_string(-1,"[ \t]+",0) ;
  1171.       if (matchsize)
  1172.      delete(point-matchsize,point) ;
  1173.       stuff("\t") ;
  1174.       insert_table_counter() ;
  1175.       }
  1176. }
  1177.  
  1178. /*=============================================================*/
  1179. /*=============================================================*/
  1180.  
  1181. void fix_unnumbered_tables()
  1182. {
  1183.    spot start = alloc_spot(1) ;
  1184.    
  1185.    *start = point ;
  1186.    point = 0 ;
  1187.    while (search(1,"\n\n"))
  1188.       {
  1189.       switch(curchar())
  1190.      {
  1191.      case 'C':
  1192.         if (parse_string(1,"Call ") != 0)
  1193.            {
  1194.            /* we got Call..., we know it doesn't have a table number */
  1195.            insert_table_counter() ;
  1196.            stuff("\n") ;
  1197.            }
  1198.         break ;
  1199.      case 'V':
  1200.         if (parse_string(1,"Values ") != 0)
  1201.            {
  1202.            /* we know this Values... doesn't have a table number */
  1203.            insert_table_counter() ;
  1204.            stuff("\n") ;
  1205.            }
  1206.         break ;
  1207.      case 'B':
  1208.         if (parse_string(1,"Bitfields ",0) == 0)
  1209.            break ;
  1210.         nl_forward() ;    /* skip to start of next line */
  1211.         maybe_append_table_number() ;
  1212.         break ;
  1213.      case 'F':
  1214.         if (parse_string(1,"Format ",0) == 0)
  1215.            break ;
  1216.         nl_forward() ;    /* skip to start of next line */
  1217.         maybe_append_table_number() ;
  1218.         break ;
  1219.      default:
  1220.         /* not a table header, so ignore it */
  1221.         break ;
  1222.      }
  1223.       }
  1224.    point = *start ;
  1225.    free_spot(start) ;
  1226. }
  1227.  
  1228. /*=============================================================*/
  1229. /*=============================================================*/
  1230.  
  1231. int *gather_table_numbers(new_numbers)
  1232. int *new_numbers ;
  1233. {
  1234.    int tcount[9] ;
  1235.    char counter[6] ;
  1236.    int old_number ;
  1237.    int table_type ;
  1238.    spot start = alloc_spot(1) ;
  1239.    save_var case_fold = 0 ;
  1240.    
  1241.    tcount[0] = tcount[1] = tcount[2] = tcount[3] = tcount[4] = tcount[5] = 0 ;
  1242.    tcount[6] = tcount[7] = tcount[8] = 0 ;
  1243.    *start = point ;
  1244.    point = 0 ;
  1245.    while (search(1,"(Table "))
  1246.       {
  1247.       char *tbl ;
  1248.       int table_offset ;
  1249.       grab(point,point+5,counter) ;
  1250.       tbl = index(table_ID_letters,counter[0]) ;
  1251.       if (tbl)
  1252.      table_offset = (tbl-table_ID_letters) ;
  1253.       else
  1254.      table_offset = 0 ;
  1255.       old_number = strtoi(counter+1,10) + 10000*table_offset ;
  1256.       table_type = (table_offset >= ID_LETTER_OFFSET)
  1257.              ? (table_offset-ID_LETTER_OFFSET+1)
  1258.              : 0 ;
  1259.       new_numbers[old_number] = ++(tcount[table_type]) ;
  1260.       }
  1261.    point = *start ;
  1262.    free_spot(start) ;
  1263.    return new_numbers ;
  1264. }
  1265.  
  1266. /*=============================================================*/
  1267. /*=============================================================*/
  1268.  
  1269. int adjust_table_numbers(new_numbers, dangling)
  1270. int *new_numbers ;
  1271. int dangling ;
  1272. {
  1273.    char counter[6] ;
  1274.    int old_number ;
  1275.    int old_type ;
  1276.    char *tbl ;
  1277.    int table_offset ;
  1278.    spot start = alloc_spot(1) ;
  1279.    
  1280.    *start = point ;
  1281.    point = 0 ;
  1282.    while (search(1,"(Table "))
  1283.       {
  1284.       grab(point,point+5,counter) ;
  1285.       tbl = index(table_ID_letters,counter[0]) ;
  1286.       if (tbl)
  1287.      {
  1288.      table_offset = 10000*(tbl-table_ID_letters) ;
  1289.      }
  1290.       else
  1291.      table_offset = 0 ;
  1292.       old_number = strtoi(counter+1,10) + table_offset ;
  1293.       old_type = (counter[0] >= '0' && counter[0] <= '9') ? 0 : counter[0] ;
  1294.       if (old_number > 0)
  1295.      {
  1296.      delete(point,point+5) ;
  1297.      if (old_type)
  1298.         bprintf("%c%04d",old_type,new_numbers[old_number]%10000) ;
  1299.      else
  1300.         bprintf("%05d",new_numbers[old_number]) ;
  1301.      }
  1302.       }
  1303.    point = 0 ;
  1304.    while (re_search(1,"[, \t]%#[0-9CFIMPRS][0-9][0-9][0-9][0-9]"))
  1305.       {
  1306.       grab(point-5,point,counter) ;
  1307.       tbl = index(table_ID_letters,counter[0]) ;
  1308.       if (tbl)
  1309.      table_offset = 10000*(tbl-table_ID_letters) ;
  1310.       else
  1311.      table_offset = 0 ;
  1312.       old_number = strtoi(counter+1,10) + table_offset ;
  1313.       old_type = (counter[0] >= '0' && counter[0] <= '9') ? 0 : counter[0] ;
  1314.       if (old_number > 0)
  1315.      {
  1316.      if (new_numbers[old_number])
  1317.         {
  1318.         delete(point-5,point) ;
  1319.         if (old_type)
  1320.            bprintf("%c%04d",old_type,new_numbers[old_number]) ;
  1321.         else
  1322.            bprintf("%05d",new_numbers[old_number]) ;
  1323.         }
  1324.      else /* dangling xref */
  1325.         {
  1326.         dangling++ ;
  1327.         point -= 5 ;
  1328.         stuff("?") ;
  1329.         point += 5 ;
  1330.         }
  1331.      }
  1332.       }
  1333.    point = *start ;
  1334.    free_spot(start) ;
  1335.    return dangling ;
  1336. }
  1337.  
  1338. /*=============================================================*/
  1339. /*=============================================================*/
  1340.  
  1341. int get_list_file(list_file)
  1342. char *list_file ;
  1343. {
  1344.    char abs_filename[FNAMELEN] ;
  1345.    strcpy(abs_filename,list_file) ;
  1346.    absolute(abs_filename) ;
  1347.    return find_it(abs_filename,1) ;
  1348. }
  1349.  
  1350. /*=============================================================*/
  1351. /*=============================================================*/
  1352.  
  1353. command renumber_tables()
  1354. {
  1355.    int *new_numbers ;
  1356.    int num_tables ;
  1357.    int dangling ;
  1358.    int i ;
  1359.    
  1360.    for (i = 0 ; list_files[i] ; i++)
  1361.       {
  1362.       if (get_list_file(list_files[i]) == 0)
  1363.      {
  1364.      say("Renumber Pass 1: numbering unnumbered tables (%s)",
  1365.          list_files[i]) ;
  1366.      fix_unnumbered_tables() ;
  1367.      }
  1368.       else
  1369.      say("Renumber Pass 1: forced to skip %s") ;
  1370.       }
  1371.    num_tables = 10000*strlen(table_ID_letters) ;
  1372.    new_numbers = (int*)malloc(num_tables*sizeof(int)) ;
  1373.    if (!new_numbers)
  1374.       {
  1375.       say("Out of memory!") ;
  1376.       return ;
  1377.       }
  1378.    for (i = 0 ; i < num_tables ; i++)
  1379.       new_numbers[i] = 0 ;
  1380.    for (i = 0 ; list_files[i] ; i++)
  1381.       {
  1382.       if (get_list_file(list_files[i]) == 0)
  1383.      {
  1384.      say("Renumber Pass 2: gathering table numbers (%s)",
  1385.          list_files[i]) ;
  1386.      gather_table_numbers(new_numbers) ;
  1387.      }
  1388.       else
  1389.      say("Renumber Pass 2: forced to skip %s") ;
  1390.       }
  1391.    dangling = 0 ;
  1392.    for (i = 0 ; list_files[i] ; i++)
  1393.       {
  1394.       if (get_list_file(list_files[i]) == 0)
  1395.      {
  1396.      say("Renumber Pass 3: adjusting table numbers (%s)",
  1397.          list_files[i]) ;
  1398.      dangling = adjust_table_numbers(new_numbers,dangling) ;
  1399.      }
  1400.       else
  1401.      say("Renumber Pass 3: forced to skip %s") ;
  1402.       }
  1403.    free(new_numbers) ;
  1404.    if (dangling)
  1405.       say("%d dangling cross-references, search for '#?'",dangling) ;
  1406.    else
  1407.       say("Done") ;
  1408. }
  1409.  
  1410. /*=============================================================*/
  1411. /*=============================================================*/
  1412.  
  1413. command make_distribution()
  1414. {
  1415.    int i ;
  1416.    
  1417.    for (i = 0 ; list_files[i] ; i++)
  1418.       {
  1419.       /* switch to proper buffer, or load if not yet in a buffer */
  1420.       if (get_list_file(list_files[i]) == 0)
  1421.      {
  1422.      say("Setting divider lines (%s)",list_files[i]) ;
  1423.      point = size() ;
  1424.      while (point > 0)
  1425.         if (!number_one_int())
  1426.            break ;
  1427.      }
  1428.       else
  1429.      say("Forced to skip %s !",list_files[i]) ;
  1430.       }
  1431.    for (i = 0 ; list_files[i] ; i++)
  1432.       {
  1433.       /* switch to proper buffer, or load if not yet in a buffer */
  1434.       if (get_list_file(list_files[i]) == 0)
  1435.      {
  1436.      say("Tabifying file (%s)",list_files[i]) ;
  1437.      mark = 0 ;
  1438.      point = size() ;
  1439.      tabify_region() ;
  1440.      }
  1441.       }
  1442.    renumber_tables() ;
  1443.    save_all_buffers() ;
  1444.    say("Ready for distribution") ;
  1445.    point = 0 ;
  1446.    /* !!! should also split main list automatically */
  1447. }
  1448.  
  1449. /*=============================================================*/
  1450. /*=============================================================*/
  1451.  
  1452. void find_table_counter()
  1453. {
  1454.    save_var point = (size() > 8000) ? size() - 8000 : 0 ;
  1455.  
  1456.    search(1,"Highest Table Number = ") ;
  1457.    table_counter = alloc_spot(1) ;
  1458. }
  1459.  
  1460. /*=============================================================*/
  1461. /*=============================================================*/
  1462.  
  1463. char filter_cmd[128] = "" ;
  1464.  
  1465. command filter_region()
  1466. {
  1467.    char new_filter_cmd[128] ;
  1468.    get_strdef(new_filter_cmd,"Filter region through",filter_cmd) ;
  1469.    strcpy(filter_cmd,new_filter_cmd) ;
  1470.    if (filter_cmd[0] != 0)
  1471.       {
  1472.       int size ;
  1473.       int fd ;
  1474.       char *commandline ;
  1475.       char *argptr ;
  1476.       int numargs = 0 ;
  1477.       char filename[128] ;
  1478.       char outputfile[128] ;
  1479.       int start = point ;
  1480.       int end = mark ;
  1481.       if (end < start)
  1482.      {
  1483.      start = mark ;
  1484.      end = point ;
  1485.      }
  1486.       size = end - start ;
  1487.       make_temp_file(filename,3*size) ;
  1488.       /* Eps7.0 always generates same temp file!  Thus, we have to manually */
  1489.       /* generate a second file name for use as the output file */
  1490.       strcpy(outputfile,filename) ;
  1491.       strcat(outputfile,"_2") ;
  1492.       delete_file(filename) ;
  1493.       if (write_part(filename,strip_returns,start,end) != 0)
  1494.      {
  1495.      delete_file(filename) ;
  1496.      return ;
  1497.      }
  1498.       fd = lowopen(outputfile,3) ;
  1499.       if (fd != -1)
  1500.      lowclose(fd) ;
  1501.       /* execute the command on the temporary file */
  1502.       commandline = malloc(strlen(filter_cmd)+strlen(filename)+strlen(outputfile)+6) ;
  1503.       if (!commandline)
  1504.      {
  1505.      say("out of memory....") ;
  1506.      delete_file(filename) ;
  1507.      return ;
  1508.      }
  1509.       argptr = strstr(filter_cmd,"%s") ;
  1510.       if (argptr)
  1511.      {
  1512.      numargs++ ;
  1513.      argptr = strstr(argptr+1,"%s") ;
  1514.      if (argptr)
  1515.         numargs++ ;
  1516.      }
  1517.       switch (numargs)
  1518.      {
  1519.      case 0:
  1520.         sprintf(commandline,"%s <%s >%s",filter_cmd,filename,outputfile) ;
  1521.         break ;
  1522.      case 1:
  1523.         sprintf(commandline,filter_cmd,filename) ;
  1524.         strcat(commandline," >") ;
  1525.         strcat(commandline,outputfile) ;
  1526.         break ;
  1527.      case 2:
  1528.         sprintf(commandline,filter_cmd,filename,outputfile) ;
  1529.         break ;
  1530.      }
  1531.       shell("",commandline,"") ;
  1532.       free(commandline) ;
  1533.       delete_file(filename) ;
  1534.       /* read back the result of the filtering */
  1535.       kill_region() ;
  1536.       if (do_insert_file(outputfile,strip_returns) != 0)
  1537.      {
  1538.      kill_region() ;     /* remove any partially-read data */
  1539.      yank() ;        /* restore region to pre-filter state */
  1540.      }
  1541.       delete_file(outputfile) ;
  1542.       }
  1543. }
  1544.  
  1545. /*=============================================================*/
  1546. /*  Coloring functions for Epsilon v7.0+               */
  1547. /*=============================================================*/
  1548.  
  1549. #if EELVERSION >= 70
  1550. int int_recolor_range(from, to)
  1551. int from, to ;
  1552. {
  1553.    if (from >= to)
  1554.       return to ;
  1555.    set_character_color(from,to,-1) ;
  1556.    save_var point, matchstart, matchend ;
  1557.    point = from ;
  1558.    if (to > size())
  1559.       to = size() ;
  1560.    while (point < to)
  1561.       {
  1562.       int start = point ;
  1563.       int len ;
  1564.       char c = curchar() ;
  1565.       if (c >= 'A' && c <= 'V')
  1566.      {
  1567.      if (parse_string(1,table_headers,NULL) != 0)
  1568.         {
  1569.         nl_forward() ;
  1570.         point-- ;
  1571.         set_character_color(start,point,color_class c_comment) ;
  1572.         }
  1573.      else if ((len = parse_string(1,all_sections,NULL)) > 0)
  1574.         set_character_color(start,start+len,color_class c_function) ;
  1575.      }
  1576.       else if (c == '\t' &&
  1577.            (len = parse_string(1,indented_sections,NULL)) != 0)
  1578.      {
  1579.      while (curchar() == '\t')
  1580.         {
  1581.         point++ ;
  1582.         len-- ;
  1583.         }
  1584.      set_character_color(point,point+len,color_class c_function) ;
  1585.      }
  1586.       nl_forward() ;
  1587.       }
  1588.    return point ;
  1589. }
  1590. #endif /* Epsilon v7.0+ */
  1591.  
  1592. #if EELVERSION >= 70
  1593. int int_recolor_from_here(safe)
  1594. int safe ;
  1595. {
  1596.    save_var point ;
  1597.    if (safe != point)
  1598.       {
  1599.       to_begin_line() ;            /* start of line is always 'safe' */
  1600.       }
  1601.    return point ;
  1602. }
  1603. #endif /* Epsilon v7.0+ */
  1604.  
  1605. /*=============================================================*/
  1606. /* Put the current buffer into IntList major mode           */
  1607. /*=============================================================*/
  1608.  
  1609. command intlist_mode()
  1610. {
  1611.    mode_keys = intlist_tab ;
  1612.    intlist_tab[')'] = intlist_tab[']'] = (short) show_matching_delimiter;
  1613.    delete_hacking_tabs = 0 ;
  1614.    major_mode = strsave("IntList") ;
  1615.    auto_indent = 0 ;
  1616.    margin_right = 79 ;
  1617.    want_backups = 1 ;
  1618.    undo_size = 200000 ;     /* less than default 500,000 since list is so big */
  1619.    find_table_counter() ;
  1620. #if EELVERSION >= 70
  1621.    recolor_range = int_recolor_range ;
  1622.    recolor_from_here = int_recolor_from_here ;
  1623.    if (want_code_coloring)
  1624.       when_setting_want_code_coloring() ;
  1625. #endif /* Epsilon v7.0+ */
  1626.    make_mode() ;
  1627. }
  1628.  
  1629. when_loading()
  1630. {
  1631.    char *curbuf ;
  1632.    int i ;
  1633.    
  1634.    want_backups = want_backups.default = 1 ;
  1635.    strcpy(backup_name,"%pbak/%b%e") ;        /* put backups in BAK subdir */
  1636.    one_window() ;
  1637.    intlist_mode() ;
  1638.    if (exist("interrup.1st"))
  1639.       {
  1640.       curbuf = bufname ;
  1641.       bufname = "interrup.1st" ;
  1642.       intlist_mode() ;
  1643.       want_code_coloring = 0 ;
  1644.       when_setting_want_code_coloring() ;
  1645.       bufname = curbuf ;
  1646.       }
  1647.    for (i = 0 ; list_files[i] ; i++)
  1648.       {
  1649.       if (exist(list_files[i]))
  1650.      {
  1651.      curbuf = bufname ;
  1652.      bufname = list_files[i] ;
  1653.      intlist_mode() ;
  1654.      bufname = curbuf ;
  1655.      }
  1656.       }
  1657. #if EELVERSION >= 70
  1658.    strcpy(mode_end," %d%p%S%>C%c") ;
  1659. #endif /* Epsilon v7.0+ */
  1660. #if EELVERSION >= 60 && EELVERSION < 70
  1661.    strcpy(mode_end," %d%p%S") ;
  1662. #endif /* Epsilon v6.x */
  1663. }
  1664.  
  1665. /*=============================================================*/
  1666. /* automagically switch into interrupt list mode on .LST and .1ST files */
  1667.  
  1668. suffix_lst()   { intlist_mode(); }
  1669. suffix_1st()   { intlist_mode(); }
  1670.  
  1671. /* end of file intlist.e */
  1672.